﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data;

namespace Utility
{
    public static class GridViewHelper
    {
        private static GridViewRow prevGridRow;
        public static string JOINED_CSS_CLASS = "GridJoined";

        public static T FindTypedControlInRow<T>(string controlid, GridViewRow row) where T : Control
        {
            Control c = FindControlInRow(controlid, row);
            if (c != null)
            {
                return (T)c;
            }
            return default(T);
        }

        public static Control FindControlInRow(string controlid, GridViewRow row)
        {
            foreach (TableCell cell in row.Cells)
            {
                Control c = cell.FindControl(controlid);
                if (c != null)
                {
                    return (Control)c;
                }
            }
            return null;
        }


        public static int GetDataKeyInGridViewRowCommandEvent(object sender, GridViewCommandEventArgs e)
        {
            GridView grd = (GridView)sender;
            GridViewRow row = GetRowInGridViewRowCommandEvent(sender, e);
            return int.Parse(grd.DataKeys[GetRowInGridViewRowCommandEvent(sender, e).RowIndex].Value.ToString());
        }


        public static GridViewRow GetRowInGridViewRowCommandEvent(object sender, GridViewCommandEventArgs e)
        {
            GridView grd = (GridView)sender;
            return ((Control)(e.CommandSource)).Parent.Parent as GridViewRow;
        }

        public static bool CheckGridViewHasDataRow(GridView gridView)
        {
            if (gridView.Rows.Count == 0)
            {
                return false;
            }
            else if (gridView.Rows.Count == 1)
            {
                return
                    !((gridView.Rows[0].Cells.Count == 1) &&
                      (gridView.Rows[0].Cells[0].ColumnSpan == gridView.Columns.Count));
            }
            else
            {
                return true;
            }
        }


        public static GridViewRow FindRowByControlsValue(GridView gridView, string controlID, string controlValue)
        {

            if (!CheckGridViewHasDataRow(gridView))
            {
                return null;
            }
            foreach (GridViewRow row in gridView.Rows)
            {
                Control c = FindControlInRow(controlID, row);

                if (c != null && controlValue.Trim() == ControlHelper.GetControlValue(c).Trim())
                    return row;
            }
            return null;
        }

        public static List<int> GetSelectRowIndexs(GridView gridView, string selectCheckBoxControlID)
        {
            List<int> selectIndex = new List<int>();

            if (!CheckGridViewHasDataRow(gridView))
            {
                return selectIndex;
            }
            foreach (GridViewRow gridViewRow in gridView.Rows)
            {
                if (gridViewRow.RowType == DataControlRowType.DataRow)
                {
                    Control chk = FindControlInRow(selectCheckBoxControlID,
                                                   gridViewRow);
                    if (chk is CheckBox)
                    {
                        CheckBox wchk = (CheckBox)chk;
                        if (wchk.Checked)
                            selectIndex.Add(gridViewRow.RowIndex);
                    }
                    else if (chk is HtmlInputCheckBox)
                    {
                        HtmlInputCheckBox hchk = (HtmlInputCheckBox)chk;
                        if (hchk.Checked)
                            selectIndex.Add(gridViewRow.RowIndex);
                    }
                }
            }
            return selectIndex;
        }

        public static List<int> GetSelectDataKeys(GridView gridView, string selectCheckBoxControlID)
        {
            List<int> selectDataKeys = new List<int>();

            if (!CheckGridViewHasDataRow(gridView))
            {
                return selectDataKeys;
            }
            foreach (GridViewRow gridViewRow in gridView.Rows)
            {
                if (gridViewRow.RowType == DataControlRowType.DataRow)
                {
                    Control chk = FindControlInRow(selectCheckBoxControlID,
                                                   gridViewRow);
                    if (chk is CheckBox)
                    {
                        CheckBox wchk = (CheckBox)chk;
                        if (wchk.Checked)
                            selectDataKeys.Add(int.Parse(gridView.DataKeys[gridViewRow.RowIndex].ToString()));
                    }
                    else if (chk is HtmlInputCheckBox)
                    {
                        HtmlInputCheckBox hchk = (HtmlInputCheckBox)chk;
                        if (hchk.Checked)
                            selectDataKeys.Add(int.Parse(gridView.DataKeys[gridViewRow.RowIndex].ToString()));
                    }
                }
            }
            return selectDataKeys;
        }


        public static string GenerateSelectAllCheckBoxScript(string gridViewID)
        {
            string script =
                @"<script type='text/javascript'>
    function $GridViewIDCheckAll(oCheckbox)
     {
       var GridView1 = document.getElementById('$GridViewID');
           for(i = 1;i < GridView1.rows.length; i++)
           {
            GridView1.rows[i].cells[0].getElementsByTagName('INPUT')[0].checked = oCheckbox.checked & !GridView1.rows[i].cells[0].getElementsByTagName('INPUT')[0].isDisabled;
           }
      }
    </script>";

            script = script.Replace("$GridViewID", gridViewID);

            return script;
        }


        public static void RegisterGridViewSelectAllCheckBoxScript(Page page, GridView gridView, string chkSelectAllID)
        {

            if (!page.ClientScript.IsStartupScriptRegistered(page.GetType(), gridView.ClientID + "SelectAll"))
            {
                string regscript = GenerateSelectAllCheckBoxScript(gridView.ClientID);
                page.ClientScript.RegisterStartupScript(page.GetType(), gridView.ClientID + "SelectAll", regscript);

                Control chk = FindControlInRow(chkSelectAllID, gridView.HeaderRow);

                if (chk is CheckBox)
                {
                    ((CheckBox)chk).Attributes["onclick"] =
                    gridView.ClientID + "CheckAll(this)";
                }
                else if (chk is HtmlInputCheckBox)
                {
                    ((HtmlInputCheckBox)chk).Attributes["onclick"] =
                    gridView.ClientID + "CheckAll(this)";
                }
            }
        }

        public static void setHeaderStyle(object sender, GridViewRowEventArgs e)
        {
            e.Row.CssClass = "RowHead";

            int index = e.Row.Cells.Count;

            Literal Literal1 = new Literal();
            Literal1.EnableViewState = false;
            Literal1.Text = e.Row.Cells[index - 1].Text + "</th></tr><tr>";
            e.Row.Cells[index - 1].Controls.Add(Literal1);
            e.Row.Cells.Add(new TableHeaderCell());
            e.Row.Cells[index].Attributes.Add("colspan", index.ToString());
            e.Row.Cells[index].Style.Add(HtmlTextWriterStyle.Height, "5px");
            e.Row.Cells[index].Style.Add(HtmlTextWriterStyle.BackgroundColor, "#FFFFFF");
        }

        public static void setDataRowStyle(object sender, GridViewRowEventArgs e)
        {
            e.Row.Style.Add(HtmlTextWriterStyle.Height, "35px");


            if (e.Row.RowIndex % 2 == 1)
            {

                e.Row.CssClass = "Row1";
                e.Row.Attributes.Add("onmouseout", "$(this).addClass('Row1').removeClass('RowOver');");
                e.Row.Attributes.Add("onmouseover", "$(this).addClass('RowOver').removeClass('Row1');");
            }
            else
            {

                e.Row.CssClass = "Row2";
                e.Row.Attributes.Add("onmouseout", "$(this).addClass('Row2').removeClass('RowOver');");
                e.Row.Attributes.Add("onmouseover", "$(this).addClass('RowOver').removeClass('Row2');");
            }
        }

        public static void setSorting(object sender, GridViewSortEventArgs e, StateBag ViewState)
        {


            GridView GridView1 = sender as GridView;

            if (ViewState["SortDirection"] == null)
            {
                ViewState["SortDirection"] = SortDirection.Descending;
            }
            for (int i = 0; i <= ((GridView)sender).Columns.Count - 1; i++)
            {
                string strHeaderText = GridView1.Columns[i].HeaderText;
                strHeaderText = strHeaderText.Replace("▲", "").Replace("▼", "");
                GridView1.Columns[i].HeaderText = strHeaderText;
            }

            int Columns_i = 0;
            for (int i = 0; i <= GridView1.Columns.Count - 1; i++)
            {
                if (e.SortExpression == GridView1.Columns[i].SortExpression)
                {
                    Columns_i = i;
                    if (ViewState["SortDirection"].ToString() == SortDirection.Ascending.ToString())
                    {
                        e.SortDirection = SortDirection.Descending;
                        GridView1.Columns[i].HeaderText = GridView1.Columns[i].HeaderText + "▼";
                        ViewState["SortDirection"] = SortDirection.Descending;
                    }
                    else
                    {
                        e.SortDirection = SortDirection.Ascending;
                        GridView1.Columns[i].HeaderText = GridView1.Columns[i].HeaderText + "▲";
                        ViewState["SortDirection"] = SortDirection.Ascending;
                    }
                }
            }


            ViewState["SortField"] = e.SortExpression;
        }

        public static void setDataBinding(GridView GridView1, SqlDataSource SqlDataSource1, StateBag ViewState)
        {
            using (DataView dv = SqlDataSource1.Select(new DataSourceSelectArguments()) as DataView)
            {

                if ((ViewState["SortDirection"] == null) ||
                        (ViewState["SortField"] == null))
                {
                    GridView1.DataSource = dv;
                    GridView1.DataBind();
                }
                else
                {
                    //using (DataView dv = ds.Tables[0].DefaultView)
                    {

                        string strSort = ViewState["SortField"].ToString();
                        if (ViewState["SortDirection"].ToString() == SortDirection.Descending.ToString())
                            strSort += " DESC";

                        dv.Sort = strSort;

                        GridView1.DataSource = dv;
                        GridView1.DataBind();
                    }
                }
            }
        }

        public static bool IsNextRow(GridViewRow row, int from, int to)
        {
            bool isNext = false;

            if (prevGridRow == null)
            {
                isNext = true;
            }
            else
            {
                for (int columnNum = from; columnNum <= to; ++columnNum)
                {
                    if (prevGridRow.Cells[columnNum].Text != row.Cells[columnNum].Text)
                    {
                        isNext = true;
                        break;
                    }
                }
            }

            prevGridRow = row;

            return isNext;
        }

        public static TableRow GetRow(GridView gridView, int rowNumber)
        {
            return gridView.Rows[rowNumber];
        }

        public static TableCell GetCell(GridView gridView, int rowNumber, int columnNumber)
        {
            // CssClass が "joined" なら 1 行上のセルを参照する
            while (GetRow(gridView, rowNumber).Cells[columnNumber].CssClass == JOINED_CSS_CLASS)
            {
                rowNumber -= 1;
            }

            return GetRow(gridView, rowNumber).Cells[columnNumber];
        }

        public static string GetText(GridView gridView, int rowNumber, int columnNumber)
        {
            // セルに表示されているテキストを取り出す
            return GetText(GetCell(gridView, rowNumber, columnNumber));
        }

    

        /// <summary>
        /// セルに表示されているテキストを取り出す
        /// </summary>
        /// <param name="cell">セル</param>
        /// <returns>セルに表示されているテキスト</returns>
        public static string GetText(TableCell cell)
        {
            foreach (Control control in cell.Controls)
            {
                // Control のテキストを返す
                if (control is TextBox)
                {
                    return ((TextBox)control).Text;
                }
                else if (control is DropDownList)
                {
                    return ((DropDownList)control).Text;
                }
                else if (control is CheckBox)
                {
                    return ((CheckBox)control).Checked.ToString();
                }
                else if (!(control is LiteralControl || control is DataBoundLiteralControl))
                {
                    throw new NotImplementedException();
                    // TODO
                    //return ((object)control).Text;
                }
            }

            // Control が見つからなかったため、 BoundColumn の テキストを返す
            return cell.Text;
        }

        public static void AddBoundColumn(GridView gridView,
        string dataField, string headerText)
        {
            BoundField field = new BoundField();

            field.DataField = dataField;
            field.HeaderText = headerText;

            gridView.Columns.Add(field);
        }

        /// <summary>
        /// GridView に列を追加する
        /// </summary>
        /// <param name="gridView">対象の GridView</param>
        /// <param name="itemTemplate">ITemplate</param>
        /// <param name="headerText">HeaderText</param>
        public static void AddTemplateColumn(GridView gridView,
            ITemplate itemTemplate, string headerText)
        {
            TemplateField field = new TemplateField();

            field.ItemTemplate = itemTemplate;
            field.HeaderText = headerText;

            gridView.Columns.Add(field);
        }

    }

}


